<?php
declare (strict_types = 1);
namespace app\api\controller;

use think\Request;
use think\Exception;
use app\BaseController;
use think\facade\{Db, Cache, Env, Log};

use think\exception\ValidateException;

use app\api\validate\{UsersValidate};
use app\api\model\{Users, Card, Goods, Code};

class LoginController extends BaseController
{
    /** 获取openid */
    public function getOpenId()
    {
        $data = input('post.');

        // 验证数据
        try{
            validate(UsersValidate::class)->scene('openid')->check($data);
        }catch(ValidateException $e){
            $this->error_back($e->getError());
        }

        $system = getSystemVal();

        $url = "https://api.weixin.qq.com/sns/jscode2session?appid={$system['appid']}&secret={$system['appsecret']}&js_code={$data['wxcode']}&grant_type=authorization_code";
        $res = curl_get($url);
        $res = json_decode($res, TRUE);

        if(isset($res['errcode'])){
            $this->error_back($res['errmsg']);
        }else{
            $this->success_back('获取成功', $res);
        }
    }

    /**
     * 微信登录
     * 错误码:
     * 40001 用户注册失败
     * 40002 用户注册更新识别码失败
     * 报错后会事务回滚 数据库不新增数据
     */
    public function login()
    {
        $userModel = new Users();
        $data = input('post.');
        Log::write($data);
        // 验证数据
        try{
            validate(UsersValidate::class)->scene('wxlogin')->check($data);
        }catch(ValidateException $e){
            $this->error_back($e->getError());
        }

        if($data['openid'] == 'undefined'){
            $this->error_back('openid is undefined');
        }

        Db::startTrans();
        try{
            // 检查unionid是否存在
            $checkunionid = $userModel->where(['unionid' => $data['unionid']])->find();

            if(empty($checkunionid)){
                $checkopenid = $userModel->where(['openid' => $data['openid']])->find();

                /** 判断openid是否注册 */
                if(empty($checkopenid)){
                    /** 绑定上级关系 */
                    $data['pid'] = 0;

                    if (isset($data['unique']) && !empty($data['unique'])) {
                        $parent_user = $userModel->where(['unique' => $data['unique']])->find();

                        if (!empty($parent_user)) {
                            $data['pid'] = $parent_user['id'];
                        }
                    }

                    /** 用户注册 */
                    $insert = $userModel->allowField(['openid', 'unionid', 'nickname', 'head_img', 'pid', 'phone', 'unique'])->save($data);
                    // $insert = $userModel->allowField(['openid', 'nickname', 'head_img', 'pid', 'phone', 'unique'])->save($data);
                
                    if($insert === false){
                        throw new Exception(40001);
                    }

                    $user_id = $userModel->id;

                    /** 生成用户推荐码 */
                    $unique = $userModel->MakeUserOnly($user_id);

                    /** 更新用户编码 */ 
                    $update = $userModel->where(['id' => $user_id])->update(['unique' => $unique]);
                    
                    if ($update === false) {
                        throw new Exception(40002);
                    }
                } else {
                    // 更新用户unionid
                    $update = $userModel->where(['id' => $checkopenid['id']])->update(['unionid' => $data['unionid']]);

                    if($update === false){
                        throw new Exception(40003);
                    }

                    $user_id = $checkopenid['id'];
                }
            }else{
                $user_id = $checkunionid['id'];
            }

            Db::commit();
        }catch (Exception $e){
            Db::rollback();
            $this->error_back('登录失败，请稍后重试，错误码：'.$e->getMessage());
        }

        $this->success_back('登录成功', ['user_id' => $user_id, 'unionid' => $data['unionid']]);
        // $this->success_back('登录成功', ['user_id' => $user_id, 'unionid' => '']);
    }

    /** 微信信息解密 */
    public function decrypt()
    {
        $data = input('post.');

        try{
            validate(UsersValidate::class)->scene('decrypt')->check($data);
        }catch(ValidateException $e){
            $this->error_back($e->getError());
        }

        $system = getSystemVal();

        $object = new \wxdecrypt\WXBizDataCrypt($system['appid'], $data['sessionKey']);
        $errCode = $object->decryptData($data['encryptedData'], $data['iv'], $datas);

        if($errCode == 0){
            $this->success_back('解密成功', $datas);
        }else{
            $this->error_back('解密失败，errCode:'.$errCode);
        }
    }

    /** 查询微信小程序二维码 */
    public function codeunlimit()
    {
        $access_token = $this->getaccesstoken();
        $data = input('post.');

        try{
            validate(UsersValidate::class)->scene('codeunlimit')->check($data);
        }catch(ValidateException $e){
            $this->error_back($e->getError());
        }

        $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={$access_token}";

        $post_data = [
            'scene' => $data['scene'],
            'page'  => $data['page'],
        ];

        $post_json = json_encode($post_data);
        $result = curl_post($url, $post_json);

        if(json_decode($result, true)){
            $result = json_decode($result, true);
            $this->error_back(['code' => $result['errcode'], 'msg' => $result['errmsg']]);
        } else {
            $jpg = $result;
            // $url = Env::get("root_path") . "/public";
            $url = root_path() . "/public";
            $file_name = "/storage/wxcode/" . md5(date('YmdHis').rand(000, 999)).".jpg";
            $file = fopen($url . $file_name, "w");
            fwrite($file, $jpg);
            fclose($file);
            $this->success_back('查询成功', ['url' => $file_name]);
        } 
    }

    /** 获取access_token（小程序） */
    private function getaccesstoken()
    {
        $system = getSystemVal();

        $access_token = Cache::get('wx_access_token:' . $system['appid']);

        if($access_token){
            return $access_token;
        }else{
            //1.请求url地址
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$system['appid']}&secret={$system['appsecret']}";
            $res = curl_get($url);
            $res = json_decode($res, true);

            if(isset($res['errcode']) && $res['errcode']!=0){
                Log::write('AccessTokenError,ErrCode:'.$res['errcode'].',ErrMsg:'.$res['errmsg']);
            }

            $access_token = $res['access_token'];
            Cache::tag('accessToken')->set('wx_access_token:' .  $system['appid'], $access_token, 3600);

            return $access_token;
        }  
    }

    /** 发送验证码 */
    public function sendSms(){
        $data = input('post.');

        try{
            validate(UsersValidate::class)->scene('phone')->check($data);
        }catch(ValidateException $e){
            $this->error_back($e->getError());
        }

        $codeModel = new Code();

        $code_info = $codeModel->getFind(['phone' => $data['phone'], 'is_use' => 0], '*', 'id desc');

        // 5分钟内重复提交
        if (!empty($code_info['data']) && $code_info['data']['expiration_time'] -  5 * 60 > time()){
            $this->error_back("验证码已发送");
        }

        // 验证码
        $data['code'] = rand(1111, 9999);

        $codeFlag = sendSms($data['phone'], $data['code']);

        // 过期时间
        $data['expiration_time'] = strtotime('+5 minute');

        $flag = $codeModel->add($data);

        if($flag['code'] != 'ok'){
            $this->error_back($flag['msg']);
        }

        $this->success_back('验证码发送成功');
    }

    /** 消费提醒 */
    public function news_consume($user_id = 61, $admin_id = 8, $money = 999)
    {
        $user_info  = Db::name('users')->where(['id' => $user_id])->find();
        $admin_info = Db::name('admin')->where(['id' => $admin_id])->find();

        $openid       = $user_info['openid2'];
        $access_token = $this->getaccesstoken2();
        
        $data = [
            'touser'       => $openid,
            'template_id'  => 'WP5t9ZgCRGNakE7dHzwhjsOVWxiyZbzlF-LqFwMtDWg',
            'topcolor'     => '#FF0000',
            'data'         => array(
                'first'    => array('value' => "消费通知", 'color' => "#E935C9"),
                'time'     => array('value' => date("Y-m-d H:i:s"), 'color' => "#E935C9"),
                'org'      => array('value' => $admin_info['nickname'], 'color' => "#E935C9"),
                'type'     => array('value' => '微信支付','color' => "#E935C9"),
                'money'    => array('value' => '￥999', 'color' => "#E935C9"),
                'point'    => array('value' => '￥999', 'color' => "#E935C9"),
                'remark'   => array('value' => "", 'color' => "#E935C9"),
            )
        ];

        $json_data = json_encode($data);
        $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $access_token;

        $res = curl_post($url, urldecode($json_data));
        $res = json_decode($res, true);

        if($res['errcode'] == 0 && $res['errcode'] == "ok"){
            return 'ok';
        }else{
            return 'fail';
        }
    }

    /** 获取access_token(模板消息) */
    private function getaccesstoken2()
    {
        $appid     = 'wx32e802da159d88d4';
        $appsecret = '1c1e887fa34ebd536b9d64e5f6b16e42';

        $access_token = Cache::get('wx_access_token:' . $appid);

        if($access_token){
            return $access_token;
        }else{
            //1.请求url地址
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
            $res = curl_get($url);
            $res = json_decode($res, true);

            if(isset($res['errcode']) && $res['errcode'] != 0){
                Log::write('AccessTokenError,ErrCode:'.$res['errcode'].',ErrMsg:'.$res['errmsg']);
            }

            $access_token = $res['access_token'];
            Cache::tag('accessToken')->set('wx_access_token:' .  $appid, $access_token, 3600);

            return $access_token;
        }  
    }
    
    /** 用于第一次验证我们网站url合法性 */
    public function firstValid(){
        //检验签名的合法性
        if($this->_checkSignature()){
            //签名合法，告知微信公众平台服务器
            echo $_GET['echostr'];
        }
    }

    /** 验证签名 */
    private function _checkSignature(){
        //获得由微信公众平台请求的验证数据
        $signature = $_GET['signature'];
        $timestamp = $_GET['timestamp'];
        $nonce     = $_GET['nonce'];

        //将时间戳，随机字符串，token按照字母顺序排序，并连接
        $tmp_arr = array('AAA123456', $timestamp, $nonce);
        sort($tmp_arr, SORT_STRING);  // 字典顺序
        $tmp_str = implode($tmp_arr);  // 连接
        $tmp_str = sha1($tmp_str);  // sha1加密

        if($signature == $tmp_str){
            $this->responseMsg();
        }else{
            return false;
        }
    }

    /** 公众号事件 */
    public function responseMsg(){
        /** 接收微信返回的数据数据,返回的xml格式 */
        $data = file_get_contents('php://input');

        /** 将xml格式转换为数组 */
        $data = $this->xmlToArray($data);

        if(!$data){
            return true;
        }

        if($data['MsgType'] == 'event'){
            if($data['Event'] == 'subscribe'){  /** 关注事件 */
                $this->doSubscribe($data['FromUserName']);
            }else if($data['Event'] == 'unsubscribe'){  /** 取关事件 */
                $this->unsubscribe($data['FromUserName']);
            }    
        }

        return true;
    }

    /** 关注后做的事件 */
    private function doSubscribe($openid){
        $access_token = $this->getaccesstoken2();

        $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$access_token}&openid={$openid}&lang=zh_CN";
        $res = curl_get($url);
        $res = json_decode($res, TRUE);

        if(!isset($res['errcode'])){
            $userModel = new Users();
            $user_info = $userModel->getFind(['unionid' => $res['unionid']]);

            if($user_info['code'] == 'ok'){
                $userModel->edit(['id' => $user_info['data']['id'], 'openid2' => $openid, 'is_follow' => 1]);
            }
        }
    }

    /** 取消关注后做的事件 */
    private function unsubscribe($openid){
        $userModel = new Users();
        $user_info = $userModel->getFind(['openid2' => $openid]);

        if($user_info['code'] == 'ok'){
            $userModel->edit(['id' => $user_info['data']['id'], 'is_follow' => 0]);
        }
    }


    /** 数据库初始化 */
    public function del(){
        $h = 'my_';

        Db::execute("truncate table ". $h . "banner");
        Db::execute("truncate table ". $h . "card");
        Db::execute("truncate table ". $h . "card_shop");
        Db::execute("truncate table ". $h . "cash");
        Db::execute("truncate table ". $h . "code");
        Db::execute("truncate table ". $h . "coupon");
        Db::execute("truncate table ". $h . "finance_record");
        Db::execute("truncate table ". $h . "gift");
        Db::execute("truncate table ". $h . "gift_goods");
        Db::execute("truncate table ". $h . "goods");
        Db::execute("truncate table ". $h . "goods_cart");
        Db::execute("truncate table ". $h . "goods_img");
        Db::execute("truncate table ". $h . "goods_group");
        Db::execute("truncate table ". $h . "order");
        Db::execute("truncate table ". $h . "order_card");
        Db::execute("truncate table ". $h . "order_evaluate");
        Db::execute("truncate table ". $h . "order_evaluate_img");
        Db::execute("truncate table ". $h . "order_gift");
        Db::execute("truncate table ". $h . "order_goods");
        Db::execute("truncate table ". $h . "order_group");
        Db::execute("truncate table ". $h . "order_make");
        Db::execute("truncate table ". $h . "order_money");
        Db::execute("truncate table ". $h . "point_record");
        Db::execute("truncate table ". $h . "techn_cate_ids");
        Db::execute("truncate table ". $h . "techn_files");
        Db::execute("truncate table ". $h . "techn_goods");
        Db::execute("truncate table ". $h . "user_shop");
        Db::execute("truncate table ". $h . "users");
    }

    //xml转换成数组
    private function xmlToArray($xml)
    {
        //禁止引用外部xml实体
        // libxml_disable_entity_loader(true);
        $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
        $val = json_decode(json_encode($xmlstring), true);

        return $val;
    }
}